package org.hawk.gwt.ppc;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hawk.gwt.ppc.utils.AntPattern;
import org.hawk.gwt.ppc.utils.JavaPattern;
import org.hawk.gwt.ppc.utils.Pattern;

/**
 * Common operations for any type of configuration invocation.
 * 
 * @author alex.bereznevatiy@gmail.com
 * @see org.hawk.gwt.ppc.Configuration
 * @see org.hawk.gwt.ppc.MavenConfiguration
 * @see org.hawk.gwt.ppc.CmdArgs
 */
abstract class AbstractConfiguration implements Configuration {
	
	private Map<String,Object> params;
	private List<String> modules;
	
	AbstractConfiguration(Map<String,Object> params, List<String> modules) {
		this.params = new HashMap<String, Object>(params);
		this.modules = new ArrayList<String>(modules);
	}
	
	/**
	 * @return list of GWT modules to process.
	 */
	public String[] getModules(){
		return modules.toArray(new String[modules.size()]);
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.Configuration#get(java.lang.String)
	 */
	public String get(String name) {
		Object rez = get(name, null);
		return rez == null ? null : rez.toString();
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.Configuration#get(java.lang.String, java.lang.Object)
	 */
	@SuppressWarnings("unchecked")
	public <T> T get(String name, T defaultValue) {
		Object result = params.get(name);
		if(result == null){
			return defaultValue;
		}
		if (defaultValue == null || defaultValue instanceof String) {
			return (T) result.toString();
		}
		if (defaultValue instanceof Boolean) {
			return (T) Boolean.valueOf(result.toString());
		}
		
		try {
			return (T) result;
		} catch(ClassCastException ex){
		}
		
		try {
			Constructor<T> c = (Constructor<T>) defaultValue.getClass().getConstructor(String.class);
			return c.newInstance(result.toString());
		} catch (Exception ex) {
		}
		
		Log.warn("Unable to cast parameter with name '" + name + "' '" + 
				result + "' to " + defaultValue.getClass().getCanonicalName());
		
		return defaultValue;
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.Configuration#getNewPattern(java.lang.String)
	 */
	public Pattern getNewPattern(String p) {
		try {
			return getPatternClass().getConstructor(String.class).newInstance(p);
		}
		catch(Exception ex){
			Log.warn("Unable to create pattern because of exception: " + ex.toString());
		}
		return new AntPattern(p);
	}

	@SuppressWarnings("unchecked")
	private Class<? extends Pattern> getPatternClass() throws ClassNotFoundException {
		String pattern = get(PATTERN_PARAMETER,ANT_PATTERN_TYPE);
		if (pattern.equals(ANT_PATTERN_TYPE)) {
			return AntPattern.class;
		} else if (pattern.equals(JAVA_PATTERN_TYPE)) {
			return JavaPattern.class;
		}
		return (Class<? extends Pattern>)Class.forName(pattern);
	}
}
